package com.kira.scaffoldmvc.SnowFlake;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 基于Hutool的雪花ID生成工具（优化版）
 * 功能特性：
 * 1. 自动绑定workerId（避免集群冲突）
 * 2. 时钟回拨检测与容错（通过Hutool内置机制）
 * 3. 提供简洁易用的API
 */
@Slf4j  // 使用Lombok的日志注解
public class SnowflakeUtils {

    // 静态的Snowflake实例，全局唯一
    private static final Snowflake SNOWFLAKE;

    // 单机房固定为0（或通过配置读取）
    private static final long DATACENTER_ID = 0;

    // 静态初始化块，在类加载时执行
    static {

        // 初始化workerId（默认取本机IP的末段作为workerId）
        // workerId用于分布式环境下区分不同节点
        long workerId = getWorkerId();

        // 初始化datacenterId（随机生成，通常单机部署无需关心）
        // datacenterId用于扩展数据中心场景
        long datacenterId = DATACENTER_ID;

        // 通过Hutool的IdUtil创建Snowflake实例
        SNOWFLAKE = IdUtil.getSnowflake(workerId, datacenterId);

        // 记录初始化日志
        log.info("Snowflake inited. WorkerId={}, DatacenterId={}", workerId, datacenterId);

    }

    /**
     * 生成雪花ID（long格式）
     * @return 64位长度的唯一ID
     */
    public static long nextId() {
        return SNOWFLAKE.nextId();
    }

    /**
     * 生成雪花ID（字符串格式）
     * @return 字符串形式的唯一ID
     */
    public static String nextIdStr() {
        return SNOWFLAKE.nextIdStr();
    }

    /**
     * 解析雪花ID的生成时间
     * @param snowflakeId 雪花ID
     * @return 时间戳（毫秒级）
     */
    public static long parseTimestamp(long snowflakeId) {
        return SNOWFLAKE.getGenerateDateTime(snowflakeId);
    }

    /**
     * 解析雪花ID生成时间，返回精确到秒的时间字符串（格式：yy-MM-dd HH:mm:ss）
     * @param snowflakeId 雪花ID
     * @return 格式化的日期时间字符串（例如："23-12-31 23:59:59"）
     */
    public static String parseTimestampWithSeconds(long snowflakeId) {
        // 获取雪花ID中的时间戳（毫秒级）
        long timestamp = SNOWFLAKE.getGenerateDateTime(snowflakeId);

        // 格式化为 yy-MM-dd HH:mm:ss
        return DateUtil.format(new Date(timestamp), "yy-MM-dd HH:mm:ss");
    }


    // ========================= 私有方法 =========================

    /**
     * 自动获取workerId（基于本机IP末段）
     * 实现逻辑：
     * 1. 获取本机IP地址
     * 2. 提取IP最后一段数字
     * 3. 取模32保证workerId在有效范围内（0-31）
     * @return workerId
     */
    private static long getWorkerId() {
        try {
            // 获取本机IP地址
            String hostIp = NetUtil.getLocalhostStr();
            // 提取IP最后一段并转为整数
            int lastSegment = Integer.parseInt(hostIp.substring(hostIp.lastIndexOf('.') + 1));
            // 取模32保证workerId在0-31范围内
            return lastSegment % 32;
        } catch (Exception e) {
            // 异常时降级为随机生成
            log.warn("Get workerId from IP failed, fallback to random. Error: {}", e.getMessage());
            return RandomUtil.randomLong(0, 31);
        }
    }

    /**
     * 时钟回拨检测（扩展点）
     * 说明：
     * 1. Hutool的Snowflake已内置时钟回拨处理
     * 2. 如需自定义处理逻辑（如告警），可在此扩展
     */
    private static void checkClockBackwards() {
        // 默认空实现，Hutool已处理回拨
        // 可扩展功能：
        // 1. 触发告警通知
        // 2. 等待时钟同步
        // 3. 记录详细日志
    }
}